#!/bin/bash
#
# This script is used to configure the Linux kernel.
#
# It was inspired by the challenge in the original Configure script
# to ``do something better'', combined with the actual need to ``do
# something better'' because the old configure script wasn't flexible
# enough.
#
# Raymond Chen was the original author of Configure.
# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
#
# 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13
# with an empty IFS.
#
# 030995 (storner@osiris.ping.dk) - added support for tri-state answers,
# for selecting modules to compile.
#
# 180995 Bernhard Kaindl (bkaindl@ping.at) - added dummy functions for
# use with a config.in modified for make menuconfig.
#
# 301195 (boldt@math.ucsb.edu) - added help text support
#
# 281295 Paul Gortmaker - make tri_state functions collapse to boolean
# if module support is not enabled.
#
# 010296 Aaron Ucko (ucko@vax1.rockhurst.edu) - fix int and hex to accept
# arbitrary ranges
#
# 150296 Dick Streefland (dicks@tasking.nl) - report new configuration
# items and ask for a value even when doing a "make oldconfig"
#
# 200396 Tom Dyas (tdyas@eden.rutgers.edu) - when the module option is
# chosen for an item, define the macro <option_name>_MODULE
#
# 090397 Axel Boldt (boldt@math.ucsb.edu) - avoid ? and + in regular 
# expressions for GNU expr since version 1.15 and up use \? and \+.
#
# 300397 Phil Blundell (pjb27@cam.ac.uk) - added support for min/max 
# arguments to "int", allow dep_tristate to take a list of dependencies
# rather than just one.
#
# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
# texts.
#
# 102598 Michael Chastain (mec@shout.net) - put temporary files in
# current directory, not in /tmp.
#
# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
# - Improve the exit message (Jeff Ronne).
#
# 12/Jan/2001 - stolen for other uses, can still be used as is for kernel
#               davidm

#
# Make sure we're really running bash.
#
# I would really have preferred to write this script in a language with
# better string handling, but alas, bash is the only scripting language
# that I can be reasonable sure everybody has on their linux machine.
#
[ -z "$BASH" ] && { echo "Configure requires bash" 1>&2; exit 1; }

# Disable filename globbing once and for all.
# Enable function cacheing.
set -f -h

#
# Dummy functions for use with a config.in modified for menuconf
#
function mainmenu_option () {
	:
}
function mainmenu_name () {
	:
}
function endmenu () {
	:
}

function comment () {
	:
}

function help () {
	:
}

#
# define_bool sets the value of a boolean argument
#
#	define_bool define value
#
function define_bool () {
	case "$2" in
	 "y")
		echo "$1=y" >>$CONFIG
		echo "#define $1 1" >>$CONFIG_H
		;;
	 *)
		echo "# $1 is not set" >>$CONFIG
		echo "#undef $1" >>$CONFIG_H
		;;
	esac
	eval "$1=$2"
}

#
# bool processes a boolean argument
#
#	bool question define
#
function bool () {
	old=$(eval echo "\${$2}")
	def=${old:-$3}
	case "$def" in
	 "y") def="y"
	      ;;
	 *)   def="n"
	      ;;
	esac
	define_bool "$2" "$def"
}


function dep_bool () {
	ques=$1
	var=$2
	shift 2
	while [ $# -gt 0 ]; do
	  case "$1" in
	    "n")
	      define_bool "$var" "n"
	      return
	      ;;
	  esac
	  shift
	done

	bool "$ques" "$var"
}

#
# define_int sets the value of a integer argument
#
#	define_int define value
#
function define_int () {
	echo "$1=$2" >> $CONFIG
	echo "#define $1 $2" >> $CONFIG_H
	eval "$1=$x"
}

#
# int processes an integer argument with optional limits
#
#	int question define default [min max]
#
function int () {
	old=$(eval echo "\${$2}")
	def=${old:-$3}
	if [ $# -gt 3 ]; then
		min=$4
	else
		min=-2000000000    # !!
	fi
	if [ $# -gt 4 ]; then
		max=$5
	else
		max=2000000000     # !!
	fi
	if expr \( \( $def + 0 \) \>= $min \) \& \( $def \<= $max \) >/dev/null 2>&1 ; then
		define_int "$2" "$def"
	else
		echo "$2: $def value is out of range ($min, $max)"
	fi
}

#
# define_hex sets the value of a hexadecimal argument
#
#	define_hex define value
#
function define_hex () {
	echo "$1=$2" >>$CONFIG
	echo "#define $1 0x${2#*[x,X]}" >>$CONFIG_H
	eval "$1=$2"
}

#
# hex processes an hexadecimal argument
#
#	hex question define default
#
function hex () {
	old=$(eval echo "\${$2}")
	def=${old:-$3}
	def=${def#*[x,X]}
	define_hex "$2" "0x$def"
}

#
# define_string sets the value of a string argument
#
#	define_string define value
#
function define_string () {
	echo "$1=\"$2\"" >> $CONFIG
	if [ -z "$2" ]; then
		if [  $# -lt 3 -o $3 -lt 3 ]; then
			echo "#undef $1" >> $CONFIG_H
		else
			echo "#define $1 \"$2\"" >> $CONFIG_H
		fi
	else
		echo "#define $1 \"$2\"" >> $CONFIG_H
	fi
	eval "$1=\"$2\""
}

#
# string processes a string argument
#
#	string question define default
#
function string () {
	old=$(eval echo "\${$2}")
	def=${old:-$3}
	define_string "$2" "$def" $#
}

#
# choice processes a choice list (1-out-of-n)
#
#	choice question choice-list default
#
# The choice list has a syntax of:
#	NAME WHITESPACE VALUE { WHITESPACE NAME WHITESPACE VALUE }
# The user may enter any unique prefix of one of the NAMEs and
# choice will define VALUE as if it were a boolean option.
# VALUE must be in all uppercase.  Normally, VALUE is of the
# form CONFIG_<something>.  Thus, if the user selects <something>,
# the CPP symbol CONFIG_<something> will be defined and the
# shell variable CONFIG_<something> will be set to "y".
#
function choice () {
	question="$1"
	choices="$2"
	def="$3"
	set -- $choices
	while [ -n "$2" ]; do
		if [ "$(eval echo \"\${$2}\")" = "y" ]; then
			def=$1
		fi
		shift; shift
	done
	set -- $choices
	while [ -n "$2" ]; do
		if [ "$1" = "$def" ]; then
			define_bool "$2" "y"
		else
			define_bool "$2" "n"
		fi
		shift; shift
	done
}

CONFIG=.tmpconfig
CONFIG_H=.tmpconfig.h
trap "rm -f $CONFIG $CONFIG_H ; exit 1" 1 2

#
# Make sure we start out with a clean slate.
#
echo "#" > $CONFIG
echo "# Automatically generated make config: don't edit" >> $CONFIG
echo "#" >> $CONFIG

echo "/*" > $CONFIG_H
echo " * Automatically generated C config: don't edit" >> $CONFIG_H
echo " */" >> $CONFIG_H
echo "#ifndef AUTOCONF_INCLUDED" >> $CONFIG_H
echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H

CONFIG_IN=./config.in
if [ "$1" != "" ] ; then
	CONFIG_IN=$1
fi

DEFAULTS=arch/$ARCH/defconfig
if [ -f .config ]; then
	DEFAULTS=.config
fi

if [ -f $DEFAULTS ]; then
	echo "#"
	echo "# Using defaults found in" $DEFAULTS
	echo "#"
	#. $DEFAULTS
	TMP_CFG=.config-is-not.$$
	sed -e 's/\^# \([[:alnum:]_]\+\) is not set.*/\1=n/' < $DEFAULTS > $TMP_CFG
	. $TMP_CFG
	rm $TMP_CFG
else
	echo "#"
	echo "# No defaults found"
	echo "#"
fi

. $CONFIG_IN

echo "#endif /* AUTOCONF_INCLUDED */" >> $CONFIG_H

rm -f .config.old
if [ -f .config ]; then
	mv .config .config.old
fi

mv $CONFIG .config
mv $CONFIG_H autoconf.h

exit 0
